// RFC3550 6.4.2 RR: Receiver Report RTCP Packet

#include "rtp-internal.h"
#include "rtp-util.h"

void rtcp_rr_unpack(struct rtp_context *ctx, const rtcp_header_t *header, const uint8_t *ptr, size_t bytes)
{
    uint32_t i;
    rtcp_rb_t *rb;
    struct rtcp_msg_t msg;
    struct rtp_member *receiver;

    assert(24 == sizeof(rtcp_rb_t) && 4 == sizeof(rtcp_rr_t));
    if (bytes < 4 /*sizeof(rtcp_rr_t)*/ + header->rc * 24 /*sizeof(rtcp_rb_t)*/) // RR SSRC + Report Block
    {
        assert(0);
        return;
    }
    msg.ssrc = nbo_r32(ptr);
    msg.type = RTCP_RR;

    receiver = rtp_member_fetch(ctx, msg.ssrc);
    if (!receiver)
        return; // error

    assert(receiver != ctx->self);
    assert(receiver->rtcp_sr.ssrc == msg.ssrc);
    // assert(receiver->rtcp_rb.ssrc == msg.ssrc);
    receiver->rtcp_clock = rtpclock(); // last received clock, for keep-alive

    ptr += 4;
    // report block
    for (i = 0; i < header->rc; i++, ptr += 24 /*sizeof(rtcp_rb_t)*/) {
        msg.u.rr.ssrc = nbo_r32(ptr);
        // if(msg.u.rr.ssrcssrc != ctx->self->ssrc)
        //	continue; // ignore
        // rb = &receiver->rtcp_rb;

        rb = &msg.u.rr;
        rb->fraction = ptr[4];
        rb->cumulative = (((uint32_t)ptr[5]) << 16) | (((uint32_t)ptr[6]) << 8) | ptr[7];
        rb->exthsn = nbo_r32(ptr + 8);
        rb->jitter = nbo_r32(ptr + 12);
        rb->lsr = nbo_r32(ptr + 16);
        rb->dlsr = nbo_r32(ptr + 20);

        ctx->handler.on_rtcp(ctx->cbparam, &msg);
    }
}

int rtcp_rr_pack(struct rtp_context *ctx, uint8_t *ptr, int bytes)
{
    // RFC3550 6.1 RTCP Packet Format
    // An individual RTP participant should send only one compound RTCP packet per report interval
    // in order for the RTCP bandwidth per participant to be estimated correctly (see Section 6.2),
    // except when the compound RTCP packet is split for partial encryption as described in Section 9.1.
    uint32_t i;
    rtcp_header_t header;

    assert(4 == sizeof(rtcp_rr_t));
    assert(24 == sizeof(rtcp_rb_t));
    assert(rtp_member_list_count(ctx->senders) < 32);
    header.v = 2;
    header.p = 0;
    header.pt = RTCP_RR;
    header.rc = MIN(31, rtp_member_list_count(ctx->senders));
    header.length = (4 /*sizeof(rtcp_rr_t)*/ + header.rc * 24 /*sizeof(rtcp_rb_t)*/) / 4;

    if ((uint32_t)bytes < 4 + header.length * 4)
        return 4 + header.length * 4;

    nbo_write_rtcp_header(ptr, &header);

    // receiver SSRC
    nbo_w32(ptr + 4, ctx->self->ssrc);

    ptr += 8;
    // report block
    for (i = 0; i < header.rc; i++) {
        struct rtp_member *sender;

        sender = rtp_member_list_get(ctx->senders, i);
        if (0 == sender->rtp_packets || sender->ssrc == ctx->self->ssrc)
            continue; // don't receive any packet

        ptr += rtcp_report_block(sender, ptr, 24);
    }

    return (header.length + 1) * 4;
}
